package com.psychologyCommunity.Community.Contoller;

import com.alibaba.fastjson.JSONObject;
import com.psychologyCommunity.Community.entity.Message;
import com.psychologyCommunity.Community.entity.Page;
import com.psychologyCommunity.Community.entity.User;
import com.psychologyCommunity.Community.service.MessageService;
import com.psychologyCommunity.Community.service.UserService;
import com.psychologyCommunity.Community.util.CommunityConstance;
import com.psychologyCommunity.Community.util.CommunityUtil;
import com.psychologyCommunity.Community.util.HostHolder;
import org.apache.kafka.common.protocol.types.Field;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.HtmlUtils;

import java.util.*;

@Controller
public class MessageController implements CommunityConstance {
    @Autowired
    private MessageService messageService;

    @Autowired
    private HostHolder hostHolder;
    @Autowired
    private UserService userService;
    //私信列表
    @RequestMapping(path = "/letter/list",method = RequestMethod.GET)
    public String getLetterList(Model model, Page page) throws Exception{
//        Integer.valueOf("abc"); //测试 是否能弹出异常处理的页面
        //拿到当前登录的用户
        User user = hostHolder.getUser();
        //分页信息
        page.setLimit(5);
        page.setPath("/letter/list");
        //查询当前登录的用户（通过hostholder可以得到用户）的id 来查 会话数量
        page.setRows(messageService.findConversationCount(user.getId()));
        //得到一个会话列表
        List<Message> conversationList = messageService.findConversations(user.getId(), page.getSetOff(), page.getLimit());
        //因为还有各类数量信息 直接声明一个集合里面放一系列Map
        List<Map<String,Object>> conversations=new ArrayList<>();
        if(conversationList !=null){
            for (Message m :conversationList) {
                Map<String,Object> map=new HashMap<>();
                //先把每条消息的数据传进去
                map.put("conversation",m);
                //当前会话的私信数量 未读的数量放进去
                map.put("letterCount",messageService.findLetterCount(m.getConversationId()));
                map.put("unreadCount",messageService.findLetterUnreadCount(user.getId(), m.getConversationId()));

                //判断当前用户的id 是否等于消息的发起者，那么目标id就是消息的接受者，反之等于消息的接受者 ，拿目标id 就是消息的发起者
                int targetId = user.getId()==m.getFromId()?m.getToId():m.getFromId();
                map.put("target",userService.findUserById(targetId));
                conversations.add(map);
            }
        }
        model.addAttribute("conversations",conversations);
        //查询未读消息数量--这个是最顶上面的用户所有会话的未读消息shul
        int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null);
        model.addAttribute("letterUnreadSumCount",letterUnreadCount);

        int unreadCount = messageService.findUnreadCount(user.getId(), null);
        model.addAttribute("noticeUnreadCount",unreadCount);
        return "/site/letter";
    }


    //因为是点击一个会话，然后再查看会话详细的消息，所以每次请求都需要一个会话Id
    @RequestMapping(path = "/letter/detail/{conversationId}",method = RequestMethod.GET)
    public String getLetterDetails(@PathVariable("conversationId") String conversationId,Page page, Model model) {
        //显示详情 也是有多条消息 所以也是要进行分页处理
        //分页信息
        page.setLimit(5);
        page.setPath("/letter/detail/" + conversationId);//显示当前路径
        page.setRows(messageService.findLetterCount(conversationId));//设置行数

        //私信列表 --页面显示 要显示发送人的user名，头像
        List<Message> letterList = messageService.findLetters(conversationId, page.getSetOff(), page.getLimit());
        List<Map<String, Object>> letters = new ArrayList<>();
        if (letterList != null) {
            for (Message message : letterList) {
                Map<String, Object> map = new HashMap<>();
                map.put("letter", message);
                map.put("fromUser", userService.findUserById(message.getFromId()));
                letters.add(map);
            }
            //把集合发给模板
            model.addAttribute("letters", letters);

            //在当前详情页面首部 会显示私信目标Id 的名字 --可以直接从conversationId中去取
            model.addAttribute("target",getLetterTarget(conversationId));

            //把私信表里的未读的消息提取出来自动的 设置成已读
            List<Integer> ids=getLetterIds(letterList);
            if(!ids.isEmpty()){
                messageService.readMessage(ids);
            }

        }
        return "/site/letter-detail";
    }
    //判断 传进来的消息列表中的 未读数据--除了  状态是0 ，它的当前的用户得是 接受者，他才能是一个未读的状态
    private List<Integer> getLetterIds(List<Message> letterList){
        List<Integer> ids=new ArrayList<>();//用来存放 未读的id
        if(letterList !=null){
            for(Message message:letterList){
                if(hostHolder.getUser().getId()==message.getToId() && message.getStatus()==0){
                    ids.add(message.getId());
                }

            }
        }
        return ids;
    }
          //从conversationId中得到用户的目标Id
        private  User getLetterTarget(String conversation){
                String[] idFrom_To=conversation.split("_");//以_分割conversationId 会得到两个字符串
              int fromUser=Integer.parseInt(idFrom_To[0]);
              int ToUser=Integer.parseInt(idFrom_To[1]);

              if (hostHolder.getUser().getId()==fromUser) {
                  return userService.findUserById(ToUser);
              }else {
                  return  userService.findUserById(fromUser);

        }
    }


    //追加一个请求的方法--声明路径 “/letter/send”,因为是要提交内容进来，请求的方式是POST
    @RequestMapping(path = "/letter/send" ,method = RequestMethod.POST)
    @ResponseBody
    //提交的不是用户的id 而是用户名，还有提交的 信息的内容
    public String sendLetter(String toName,String content){
        Integer.valueOf("abc"); //测试 异步的页面
        User target = userService.findUserByName(toName);
        if(target==null){ //当发送目标为空，直接给个1,代表错误，并且给个提示
            return CommunityUtil.getJSONString(1,"目标用户不存在");
        }
        //如果目标用户就用 当前的数据去构造Message类型的数据
        Message message=new Message();
        message.setFromId(hostHolder.getUser().getId());
        message.setToId(target.getId());
        //两端用户id 拼接变成conversationId 但是注意一点 小的在前
        if(message.getFromId()<message.getToId()){
            message.setConversationId(message.getFromId()+"_"+message.getToId());
        }else {
            message.setConversationId(message.getToId()+"_"+message.getFromId());
        }
        message.setContent(content);
        message.setCreateTime(new Date());
        messageService.addMessage(message);

        //如果没有报错，就给页面返回0
        return CommunityUtil.getJSONString(0);
    }
    @RequestMapping(path = "/notice/list",method = RequestMethod.GET)
    public String getNoticeList(Model model){
        User user = hostHolder.getUser();
        //查询评论类 通知
        Message message=messageService.findLatestNotice(user.getId(),TOPIC_COMMENT);
        //这存在一个潜在的bug，如果这实例化了一个HashMap，但我们用户可能没有这类 通知，，下面的if 程序体中的逻辑不执行，直接就往model中存了一个空的hashMap
        //如果尝试从空的hashMap中取值肯定是取不到的 就会报错
        if(message !=null){
            Map<String ,Object> messageVO=new HashMap<>();//messageVO最终是被模板引用 要显示数据的
            messageVO.put("message",message);
            //因为content中有转移字符 ，显示之前 得从数据中 反转义回来 再存到messageVo中;可以利用HtmlUtils.htmlUnescape的html标签进行转移
            String content= HtmlUtils.htmlUnescape(message.getContent());//相当于转换成了正常显示的字符串
            Map<String,Object> data= JSONObject.parseObject(content,HashMap.class);//将字符串 转换成map类型的对象
            //从内容中得到数据传到messageVO中
            messageVO.put("user",userService.findUserById((Integer) data.get("userId")));
            messageVO.put("entityType",data.get("entityType"));
            messageVO.put("entityId",data.get("entityId"));
            messageVO.put("postId",data.get("postId"));

            int noticeCount = messageService.findNoticeCount(user.getId(), TOPIC_COMMENT);
            messageVO.put("count",noticeCount);

            int unreadCount = messageService.findUnreadCount(user.getId(), TOPIC_COMMENT);
            messageVO.put("unread",unreadCount);
            model.addAttribute("commentNotice",messageVO);
        }


        //查询点赞类通知--
      Message  messageLike=messageService.findLatestNotice(user.getId(),TOPIC_LIKE);

        if(messageLike !=null){
            Map<String ,Object>  messageVO = new HashMap<>();//messageVO最终是被模板引用 要显示数据的
            messageVO.put("message",messageLike);
            //因为content中有转移字符 ，显示之前 得从数据中 反转义回来 再存到messageVo中;可以利用HtmlUtils.htmlUnescape的html标签进行转移
            String content= HtmlUtils.htmlUnescape(messageLike.getContent());//相当于转换成了正常显示的字符串
            Map<String,Object> data= JSONObject.parseObject(content,HashMap.class);//将字符串 转换成map类型的对象
            //从内容中得到数据传到messageVO中
            messageVO.put("user",userService.findUserById((Integer) data.get("userId")));
            messageVO.put("entityType",data.get("entityType"));
            messageVO.put("entityId",data.get("entityId"));
            messageVO.put("postId",data.get("postId"));

            int noticeCount = messageService.findNoticeCount(user.getId(), TOPIC_LIKE);
            messageVO.put("count",noticeCount);

            int unreadCount = messageService.findUnreadCount(user.getId(), TOPIC_LIKE);
            messageVO.put("unread",unreadCount);
            model.addAttribute("LikeNotice",messageVO);

        }

        //查询关注类通知
       Message messageFollow=messageService.findLatestNotice(user.getId(),TOPIC_FOLLOW);
        if(messageFollow !=null){
            Map<String ,Object>  messageVO = new HashMap<>();//messageVO最终是被模板引用 要显示数据的
            //因为content中有转移字符 ，显示之前 得从数据中 反转义回来 再存到messageVo中;可以利用HtmlUtils.htmlUnescape的html标签进行转移
            String content= HtmlUtils.htmlUnescape(messageFollow.getContent());//相当于转换成了正常显示的字符串
            Map<String,Object> data= JSONObject.parseObject(content,HashMap.class);//将字符串 转换成map类型的对象
            //从内容中得到数据传到messageVO中
            messageVO.put("user",userService.findUserById((Integer) data.get("userId")));
            messageVO.put("entityType",data.get("entityType"));
            messageVO.put("entityId",data.get("entityId"));
            messageVO.put("postId",data.get("postId"));
            int noticeCount = messageService.findNoticeCount(user.getId(), TOPIC_FOLLOW);
            messageVO.put("count",noticeCount);
            int unreadCount = messageService.findUnreadCount(user.getId(), TOPIC_FOLLOW);
            messageVO.put("unread",unreadCount);
            model.addAttribute("FollowNotice",messageVO);
        }

        //查询 未读私信数量 的总数 ，以及所有主题的未读消息的总数
        int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null);
        model.addAttribute("letterUnreadCount",letterUnreadCount);
        int unreadCount = messageService.findUnreadCount(user.getId(), null);
        model.addAttribute("noticeUnreadCount",unreadCount);

        //完成之后，返回到模板
        return "/site/notice";

    }
    @RequestMapping(path = "/notice/detail/{topic}" ,method = RequestMethod.GET)
    public String getNoticeDetail(@PathVariable("topic") String topic,Page page,Model model){
        User user = hostHolder.getUser();
        page.setLimit(5);
        page.setPath("/notice/detail/"+topic);
        page.setRows(messageService.findNoticeCount(user.getId(), topic));

        List<Message> noticeList= messageService.findNotices(user.getId(), topic, page.getSetOff(), page.getLimit());
        List<Map<String,Object>> noticeVolist=new ArrayList<>();
        if(noticeList !=null){
            for (Message notice : noticeList) {
                Map<String ,Object> map=new HashMap<>();
                //通知
                map.put("notice",notice);
                //content中的内容 转译过来存到
                String content=HtmlUtils.htmlUnescape(notice.getContent());
                HashMap<String,Object> data = JSONObject.parseObject(content, HashMap.class);
                map.put("user",userService.findUserById((Integer) data.get("userId")));
                map.put("entityType",data.get("entityType"));
                map.put("entityId",data.get("entityId"));
                map.put("post",data.get("postId"));//就算不是 传入的是null，不影响

                //通知的作者
                map.put("fromUser",userService.findUserById(notice.getFromId()));
                noticeVolist.add(map);
            }
        }
        model.addAttribute("notices",noticeVolist);
        //设置已读
        List<Integer> letterIds = getLetterIds(noticeList);
        if(!letterIds.isEmpty()){
            messageService.readMessage(letterIds);
        }
        return  "/site/notice-detail";
    }

}
